﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Timers;
using System.Diagnostics;
using System.ComponentModel;

namespace WPF.TestEditor
{
    /// <summary>
    /// Interaction logic for Processing.xaml
    /// </summary>
    public partial class Processing : MahApps.Metro.Controls.MetroWindow
    {        
        public Processing(Window parent,string title, Func<ProcessingEventArgs, bool> methodToExecute)            
        {
            MethodToExecute = methodToExecute;
            InitializeComponent();
           this.Title= title;
            this.prbProgress.Minimum = 0;
            this.prbProgress.Maximum = 100;
            this.prbProgress.Value = 10;
            btnCancel.Click += new RoutedEventHandler(btnCancel_Click);
            
            updateProgress.Elapsed += new ElapsedEventHandler(updateProgress_Elapsed);
            data.Progress += new ProgressChangedEventHandler(data_Progress);
            this.Loaded += new RoutedEventHandler(Processing_Loaded);
        }

        void Processing_Loaded(object sender, RoutedEventArgs e)
        {
            var t=new System.Threading.Thread(()=>{                
                MethodToExecute(data);
                Action a=()=>this.Close();
                this.Dispatcher.Invoke(a);
            });
            t.Start();
        }
        
        void data_Progress(object sender, ProgressChangedEventArgs e)
        {
            var t = e.UserState as string;
            var v = e.ProgressPercentage;
            progresAction = () => OnProgress(t, v);
            updateProgress.Start();
        }

        ProcessingEventArgs data = new ProcessingEventArgs();
        Func<ProcessingEventArgs, bool> MethodToExecute;
              

        [DebuggerHidden]
        void updateProgress_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (progresAction == null) return;
            lock (progresAction)
            {
                this.Dispatcher.Invoke(progresAction);
                progresAction = null;
                updateProgress.Stop();
            }
        }
        Action progresAction = null;
        Timer updateProgress = new Timer() { Interval = 100 , AutoReset=true};
        
        [DebuggerHidden]
        private void OnProgress(string title, double value)
        {
            txtProgress.Text = title;
            prbProgress.Value = value;            
        }
        void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            data.InvokeCancel();
        }
    }


    public class ProcessingEventArgs : CancelEventArgs
    {
        public event EventHandler Canceled;
        public event ProgressChangedEventHandler Progress;

        public void InvokeCancel()
        {
            this.Cancel = true;

            if (Canceled != null)
                Canceled(null, null);
        }

        public void InvokeProgress(string title, int percent)
        {
            if (Progress != null)
                Progress(null, new ProgressChangedEventArgs(percent, title));
        }
    }
}
